﻿using System.Data;
using System.IO;
using DataScripter.Containers;
using DataScripter.Database;
using DataScripter.Scripting.InputSources;
using DataScripter.Scripting.Output;
using DataScripter.Scripting.Output.Sql;

namespace DataScripter.Scripting
{
    public class SpecialFieldTreatment : ISpecialFieldTreatment
    {
        private IContainer Container { get; set; }
        private ITableScriptRequest TableScriptRequest { get; set; }
        public string LookupTableName { get; set; }
        public string LookupFieldName { get; set; }
        private FieldInfo Field { get; set; }
        private FieldInfo LookupField { get; set; }
        private string LookupSql { get; set; }
        private ITableStructure LookupTable { get; set; }
        private bool VariableAlreadyDeclared { get; set; }
        private object Value { get; set; }


        public SpecialFieldTreatment(IContainer container, ITableScriptRequest tableScriptRequest, string fieldName, string lookupTableName, string lookupFieldName)
        {
            Container = container;
            TableScriptRequest = tableScriptRequest;
            LookupTableName = lookupTableName;
            LookupFieldName = lookupFieldName;
            Field = TableScriptRequest.TableStructure.Fields[fieldName];
        }

        public string VariableName { get; private set; }

        public void Initialize(IDataReader reader, Db db, SqlScriptOutputContext context)
        {
            LookupTable = Container.Resolve<IInputSource>().Resolve<IDatabaseStructure>().GetTable(LookupTableName);
            LookupField = LookupTable.Fields[LookupFieldName];
            LookupSql = string.Format("SELECT {0} FROM {1} WHERE {2}={3}", LookupField.ColumnName, LookupTable.TableName, LookupTable.PrimaryKeyFields[0], "{0}");

            string sqlValue = Field.ReadValue(reader);
            using (IDataReader lookupReader = db.ExecuteReader(string.Format(LookupSql, sqlValue)))
            {
                lookupReader.Read();
                Value = LookupField.ReadRawValue(lookupReader);
                VariableAlreadyDeclared = context.Get<IVariableContext>().HasVariableName(Field.ColumnName, Value);
                VariableName = "@" + context.Get<IVariableContext>().RequestVariableName(Field.ColumnName, Value, VariableAlreadyDeclared);
            }
        }

        public void Script(StreamWriter streamWriter)
        {
            if (VariableAlreadyDeclared) return;

            streamWriter.WriteLine("DECLARE {0} {1}", VariableName, LookupField.ConstructFullDataType());
            streamWriter.WriteLine("SELECT " + VariableName + "=" + Field.ColumnName + " FROM " + LookupTable.TableName + " WHERE " + LookupField.ColumnName + "=" + Value);
        }
    }
}